#include "stdafx.h"
#include "glThunderboltRender.h"

#include "../../xrEngine/thunderbolt.h"
#include "glThunderboltDescRender.h"
#include "glLensFlareRender.h"

glThunderboltRender::glThunderboltRender()
{
	// geom
	hGeom_model.create(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, RCache.Vertex.Buffer(), RCache.Index.Buffer());
	hGeom_gradient.create(FVF::F_LIT, RCache.Vertex.Buffer(), RCache.QuadIB);
}

glThunderboltRender::~glThunderboltRender()
{
	hGeom_model.destroy();
	hGeom_gradient.destroy();
}

void glThunderboltRender::Copy(IThunderboltRender &_in)
{
	*this = *(glThunderboltRender*)&_in;
}

void glThunderboltRender::Render(CEffect_Thunderbolt &owner)
{
	VERIFY(owner.current);

	// lightning model
	float dv = owner.lightning_phase*0.5f;
	dv = (owner.lightning_phase>0.5f) ? Random.randI(2)*0.5f : dv;

	RCache.set_CullMode(CULL_NONE);
	u32					v_offset, i_offset;

	glThunderboltDescRender *pThRen = (glThunderboltDescRender*)&*owner.current->m_pRender;

	u32					vCount_Lock = pThRen->l_model->number_vertices;
	u32					iCount_Lock = pThRen->l_model->number_indices;
	IRender_DetailModel::fvfVertexOut* v_ptr = (IRender_DetailModel::fvfVertexOut*) 	RCache.Vertex.Lock(vCount_Lock, hGeom_model->vb_stride, v_offset);
	u16*				i_ptr = RCache.Index.Lock(iCount_Lock, i_offset);
	// XForm verts
	pThRen->l_model->transfer(owner.current_xform, v_ptr, 0xffffffff, i_ptr, 0, 0.f, dv);
	// Flush if needed
	RCache.Vertex.Unlock(vCount_Lock, hGeom_model->vb_stride);
	RCache.Index.Unlock(iCount_Lock);
	RCache.set_xform_world(Fidentity);
	RCache.set_Shader(pThRen->l_model->shader);
	RCache.set_Geometry(hGeom_model);
	RCache.Render(D3DPT_TRIANGLELIST, v_offset, 0, vCount_Lock, i_offset, iCount_Lock / 3);
	RCache.set_CullMode(CULL_CCW);

	// gradient
	Fvector				vecSx, vecSy;
	u32					VS_Offset;
	FVF::LIT *pv = (FVF::LIT*) RCache.Vertex.Lock(8, hGeom_gradient.stride(), VS_Offset);
	// top
	{
		u32 c_val = iFloor(owner.current->m_GradientTop->fOpacity*owner.lightning_phase*255.f);
		u32 c = color_rgba(c_val, c_val, c_val, c_val);
		vecSx.mul(Device.vCameraRight, owner.current->m_GradientTop->fRadius.x*owner.lightning_size);
		vecSy.mul(Device.vCameraTop, -owner.current->m_GradientTop->fRadius.y*owner.lightning_size);
		pv->set(owner.current_xform.c.x + vecSx.x - vecSy.x, owner.current_xform.c.y + vecSx.y - vecSy.y, owner.current_xform.c.z + vecSx.z - vecSy.z, c, 0, 0); pv++;
		pv->set(owner.current_xform.c.x + vecSx.x + vecSy.x, owner.current_xform.c.y + vecSx.y + vecSy.y, owner.current_xform.c.z + vecSx.z + vecSy.z, c, 0, 1); pv++;
		pv->set(owner.current_xform.c.x - vecSx.x - vecSy.x, owner.current_xform.c.y - vecSx.y - vecSy.y, owner.current_xform.c.z - vecSx.z - vecSy.z, c, 1, 0); pv++;
		pv->set(owner.current_xform.c.x - vecSx.x + vecSy.x, owner.current_xform.c.y - vecSx.y + vecSy.y, owner.current_xform.c.z - vecSx.z + vecSy.z, c, 1, 1); pv++;
	}
	// center
	{
		u32 c_val = iFloor(owner.current->m_GradientTop->fOpacity*owner.lightning_phase*255.f);
		u32 c = color_rgba(c_val, c_val, c_val, c_val);
		vecSx.mul(Device.vCameraRight, owner.current->m_GradientCenter->fRadius.x*owner.lightning_size);
		vecSy.mul(Device.vCameraTop, -owner.current->m_GradientCenter->fRadius.y*owner.lightning_size);
		pv->set(owner.lightning_center.x + vecSx.x - vecSy.x, owner.lightning_center.y + vecSx.y - vecSy.y, owner.lightning_center.z + vecSx.z - vecSy.z, c, 0, 0); pv++;
		pv->set(owner.lightning_center.x + vecSx.x + vecSy.x, owner.lightning_center.y + vecSx.y + vecSy.y, owner.lightning_center.z + vecSx.z + vecSy.z, c, 0, 1); pv++;
		pv->set(owner.lightning_center.x - vecSx.x - vecSy.x, owner.lightning_center.y - vecSx.y - vecSy.y, owner.lightning_center.z - vecSx.z - vecSy.z, c, 1, 0); pv++;
		pv->set(owner.lightning_center.x - vecSx.x + vecSy.x, owner.lightning_center.y - vecSx.y + vecSy.y, owner.lightning_center.z - vecSx.z + vecSy.z, c, 1, 1); pv++;
	}
	RCache.Vertex.Unlock(8, hGeom_gradient.stride());
	RCache.set_xform_world(Fidentity);
	RCache.set_Geometry(hGeom_gradient);
	RCache.set_Shader(((glFlareRender*)&*owner.current->m_GradientTop->m_pFlare)->hShader);

#ifdef	USE_DX10
	//	Hack. Since lightning gradient uses sun shader override z write settings manually
	RCache.set_Z(TRUE);
	RCache.set_ZFunc(D3DCMP_LESSEQUAL);
#endif	//	USE_DX10

#ifdef	USE_DX10
	//	Hack. Since lightning gradient uses sun shader override z write settings manually
	RCache.set_Z(TRUE);
	RCache.set_ZFunc(D3DCMP_LESSEQUAL);
#endif	//	USE_DX10
	RCache.Render(D3DPT_TRIANGLELIST, VS_Offset, 0, 4, 0, 2);
	RCache.set_Shader(((glFlareRender*)&*owner.current->m_GradientCenter->m_pFlare)->hShader);

#ifdef	USE_DX10
	//	Hack. Since lightning gradient uses sun shader override z write settings manually
	RCache.set_Z(TRUE);
	RCache.set_ZFunc(D3DCMP_LESSEQUAL);
#endif	//	USE_DX10

#ifdef	USE_DX10
	//	Hack. Since lightning gradient uses sun shader override z write settings manually
	RCache.set_Z(TRUE);
	RCache.set_ZFunc(D3DCMP_LESSEQUAL);
#endif	//	USE_DX10
	RCache.Render(D3DPT_TRIANGLELIST, VS_Offset + 4, 0, 4, 0, 2);
}
